import { _decorator, assetManager, AudioClip, AudioSource, Color, Component, Event, ImageAsset, Input, instantiate, Label, Layout, Node, Prefab, resources, sp, Sprite, SpriteFrame, Vec3 } from 'cc';
import { Socket, GAME_DATA, LANDLORD_ELECT, POKER_PLAY_REDIRECT, Poker_1, POKER_PLAY_PASS, GAME_READY, PLAY_START, Trusted, JOIN_SUCCESS, Players, Poker, GameOverType } from '../main/lib/Net';
import { PokerHelper, PokerSell } from '../main/lib/PokerHelper';
import { GameID, Gamer, RoomInfo } from '../main/lib/StorageInfo';
import { Log, Util } from '../main/lib/Util';
import { Clearing } from './Children/Clearing';
import { Folter } from './Children/Folter';
import { Cliock } from './Children/Cliock';
import { Header } from './Children/Header';
import { BtnType as BtnType_ } from '../main/common/Alert';
import { Loding } from '../main/Loding/Loding';
import { Team } from '../Main_/script/Team';
import { Home } from '../Main_/script/Home';
import { GoldAmple } from '../main/lib/Type';
const { ccclass, property, type } = _decorator

@ccclass('Game')
// @executeInEditMode(true)
export class Game extends Component {
  static TeamData = {
    create: false,
    join: false,
    roomid: undefined
  };
  /**本类的实列 */
  static I: Game = null;
  static roomId: number = 101;//房间id
  static roomtitle: string = '';
  static uId: number = 12345;//玩家id
  static scroe: number = 100;//低分
  static fold: number = 1;//倍数
  static gamerInfoArr: Players = null;
  /** 弹窗结算面板 */
  @property(Node)
  clearing: Node = null;
  /**取消托管节点 */
  @property(Node)
  Escrow: Node = null;
  /**开始游戏|抢地主|加倍*/
  @property(Node)
  ButtonGroup: Node = null;
  /**整幅扑克图 */
  @type([SpriteFrame])
  playingCard: SpriteFrame[] = new Array(54);
  /**玩家出牌节点*/
  @property({ group: { name: '玩家出牌节点', id: 'user' }, type: [Node] })
  PlayCards: Node[] = new Array(3);
  /**玩家手牌节点 */
  @property({ group: { name: '玩家手牌', id: 'user' }, type: [Node], })
  Hands: Node[] = new Array(3);
  /**玩家节点*/
  @property({ group: { name: '玩家节点', id: 'user' }, type: [Node], })
  Gamer: Node[] = new Array(3);
  /**其他玩家匹配中的节点 */
  @property({ group: { name: '匹配中的玩家节点', id: 'user' }, type: [Node] })
  Gamer_other: Node[] = new Array(2);
  /**顶部地主三张牌*/
  @property({ group: { name: '地主牌', id: 'user' }, type: Node, })
  LandlordCard: Node = null;
  /**手里牌、对手手里牌、地主牌、已经出牌的预制体*/
  @property({ group: { name: '[手里牌预|对手里牌预|地主牌预|已出牌]预制体', id: 'user2' }, type: [Prefab] })
  PickPrefabs: Prefab[] = new Array(4);
  /**计时器 | 要不起 预制体*/
  @property([Prefab])
  gamerState: Prefab[] = new Array(2);
  /**其他需要实现功能的按钮 */
  @property([Node])
  OthersBtns: Node[] = [];
  /**音频节点 */
  @type(AudioSource)
  audioNode: AudioSource = null;
  /**动画节点 */
  @type(Node)
  atlats: Node = null;
  /**动画资源 */
  @type([sp.SkeletonData])
  skeletonS: sp.SkeletonData[] = [];
  /**底注倍数节点 */
  @type(Label)
  scoreNode: Label = null;
  /**金币倍数节点 */
  @property(Folter)
  florer: Folter = null;
  /**选中的牌 */
  selectCards: Set<string> = new Set();
  /**ws套接字 */
  ws: Socket = null;
  protected start() {
    Game.I = this;
    this.init();
  }
  protected onDestroy(): void {//销毁心跳包回调
    try {
      this.unschedule(this.ws.heard_beat_);
    } catch (error) {
      
    }
    Team.TeamData = { create: false, join: false, roomid: undefined };
  }
  init() {
    console.log(Team.TeamData);
    Game.TeamData = Team.TeamData;
    const roomConfig = new GameID();
    Game.uId = roomConfig.uid;//设置静态全局用户uid
    Game.roomId = roomConfig.roomid;//设置静态全局房间id
    Game.scroe = roomConfig.scroe;//设置房间低分
    setGamer.selfID();//这一步很重要 设置玩家自己初始id
    // this.scoreNode.string = `${roomConfig.roomtitle}\t\t低分:${roomConfig.scroe}\t\t倍数:${roomConfig.base_score}`;
    this.scoreNode.string = `${roomConfig.roomtitle}`;
    this.ws = new Socket({
      open: (ev) => {
        Log.success('连接成功!!!');
        console.log(Game.TeamData);
        if (Game.TeamData.create || Game.TeamData.join) {
          this.ws.login({ id: String(Game.uId), version: '1.0.0', mode: '1' });//登录ws
          if (Game.TeamData.join) {//是否加入房间进来的
            this.ws.JOIN_ROOM(Game.TeamData.roomid);
            setGamer.OthersNode()//显示匹配中
          } else {
            this.ws.createCREATE_ROOM(Game.roomId)//好友房
            // if (Game.TeamData.create) {//创建好友房
            // } else {//创建人机房
            //   this.ws.createPVE_ROOM(Game.roomId);//发起房间创建
            // }
          }
        } else {
          new Button(true, BtnType.GAME_STARTING);
        }
        this.ws.heard_beat_ = () => {
          console.log('心跳包发送')
          this.ws.heard_beat()
        }
        this.schedule(this.ws.heard_beat_, 15) //心跳包
      },
      close: (ev) => {
        // this.unschedule(this.ws.heard_beat_)
        // new Util.Alert().ShowAlert({
        //   msg: 'ws断开连接!',
        //   cancel: false,
        //   confrm: true,
        //   callfun: function (type: BtnType_, node: Node): void {
        //     node.destroy();
        //     Loding.start_Loding('Main_');
        //   }
        // })
        Log.error('关闭连接!!!', ev);
      },
      message: (ev) => {
        const data_ = JSON.parse(ev.data);
        const code = data_.code;
        let data = null;
        try {
          data = JSON.parse(data_.data);
        } catch (error) {
          Log.info('指令数据指令消息', data_);
        }
        // Log.info('服务端消息=====>', data_);
        Log.info('服务端指令消息=====>', code, data);
        switch (code) {
          case 'CODE_CLIENT_LOGIN':
            Log.info('游戏登录', data);
            break;
          case 'CODE_SHOW_OPTIONS':
            Log.info('游戏选项', data);
            break;
          case 'CODE_GAME_COIN_LESS':
            new Util.Alert().ShowAlert({
              msg: '金币不足',
              cancel: false,
              confrm: true,
              callfun: function (type: BtnType_, node: Node): void {
                node.destroy();
                Home.Gold = GoldAmple.noAmple;
                Loding.start_Loding('Main_');
              }
            })
            break;
          case 'CODE_ROOM_CREATE_SUCCESS':
            const sucData: GAME_DATA = data;
            new RoomInfo().setID(sucData.room.id, sucData.room.type);
            new DesktopData(sucData).setScore().setUser();
            setGamer.OthersNode()//显示匹配中
            break;
          case 'CODE_ROOM_JOIN_SUCCESS'://玩家加入
            const joinData: JOIN_SUCCESS = data;
            new RoomInfo().setID(joinData.roomId, joinData.roomType);
            new setGamer(joinData).others();
            const node = this.Gamer.find(item => item.name === joinData.clientId.toString());//找到对应id的玩家节点;
            new setGamerInfo(node, joinData);
            console.log("玩家加入查询的节点", node);
            Log.success("玩家加入", data);
            break;
          case 'CODE_GAME_STARTING': //开始游戏
            new GamerStart()//清空所有状态数据
            Header.GAME_OVER = false;//设置不嫩退出游戏
            setGamer.selfID();//这一步很重要 设置玩家自己初始id
            const startdata: GAME_DATA = data;
            const obj = startdata.players[new Gamer().uid];
            this.Gamer_other.forEach(item => {//重连显示其他玩家数据
              item.active = true //显示npc玩家节点
              item.children[0].name = String(obj[item.name]);//设置玩家节点id
              setGamer.toggleUI(item, true)//显示玩家节点上的头像节点
              // console.log('子节点id', item.children[0].name, obj[item.name]);
              const gamerdata = startdata.players[item.children[0].name];//取到玩家的数据
              new setGamerInfo(item.children[0], { avatar: gamerdata.avatar, clientNickname: gamerdata.nickname })
            });

            Game.gamerInfoArr = startdata.players;//存一个静态全局全部玩家的数据
            new GamerState(startdata.currentId).clock(startdata.timeout);//显示倒计时
            new SetCardData(startdata).setGamerID().setHandsCard();
            if (startdata.currentId === new Gamer().uid) {
              new Button(true, BtnType.LANDLORD_ELECT);
            }

            if (startdata.room.landlordId > 0) {
              new SetLandlordCard(startdata.room.landlordId.toString(), startdata.room.landlordPokers)
            }
            Log.info('游戏开始数据', data);
            console.log(startdata.players[new Gamer().uid]);

            break;
          case 'CODE_GAME_LANDLORD_ELECT': //论到谁抢地主
            Log.info('抢地主', data);
            const landlordData: LANDLORD_ELECT = data;
            if (landlordData.iFan > 0) {//设置自己的倍数
              Folter.I.setFold(landlordData.iFan)
            }
            if (landlordData.currentId === Game.uId && landlordData.trusted !== true) {
              new Button(true, BtnType.LANDLORD_ELECT);
            }
            new GamerState(landlordData.currentId).clock(landlordData.timeout);//显示倒计时
            if (landlordData.operation === 2) {//其他玩家不抢
              new GamerState(landlordData.preId).otherMsg(StateType.Elect_NO)
            }
            if (landlordData.operation === 1) {//显示其他玩家抢
              new GamerState(landlordData.preId).otherMsg(StateType.Elect_YES)
            }
            break;
          case 'CODE_GAME_READY': //谁加的倍
            const gamereadyData: GAME_READY = data;
            switch (gamereadyData.fan) {
              case 1: new GamerState(gamereadyData.id).otherMsg(StateType.CHOOSE_0); break;
              case 2: new GamerState(gamereadyData.id).otherMsg(StateType.CHOOSE_2); break;
              case 4: new GamerState(gamereadyData.id).otherMsg(StateType.CHOOSE_4); break;
            }
            Folter.I.setFold(gamereadyData.iFan)
            // this.Gamer.filter(item=>item.name === gamereadyData.id.toString())[0].children[2].children[0].removeFromParent()
            Log.info('谁加的倍', gamereadyData);
            break;
          case 'CODE_GAME_LANDLORD_CONFIRM': //确定好地主
            const confirmData: GAME_DATA = data;
            Log.info('地主牌', data);
            new SetCardData(confirmData).setHandsCard().setPlayCards();
            new SetLandlordCard(confirmData.room.landlordId.toString(), confirmData.room.landlordPokers);
            if (confirmData.players[new Gamer().uid].trusted === false) {
              new Button(true, BtnType.JIA_BEI);
            }
            break;
          case 'CODE_GAME_POKER_PLAY_START': //开始出牌
            const play_start: PLAY_START = data;
            if (play_start.currentId == Game.uId) {
              new Button(true, BtnType.PLAY_PASS).togglebtn(false, 0);
            }
            new GamerState(play_start.currentId).clock(play_start.timeout);//显示倒计时
            Log.info('开始出牌', data);
            break;
          case 'CODE_GAME_CHANGE_TRUSTEE': //托管状态
            const trustData: Trusted = data;
            SetCardData.setTrusted(trustData.clientId, trustData.trusted);

            break;
          case 'CODE_GAME_POKER_PLAY_REDIRECT': //轮到我出牌
            new GamerState(Game.uId).plass(true);//清除要不起文字
            const play_redirect: POKER_PLAY_REDIRECT = data;
            setTimeout(() => {
              new GamerState(Game.uId).clock(play_redirect.timeout);//显示倒计时
            }, 200);
            if (play_redirect.trusted) {//如果托管状态就隐藏操作按钮
              new Button(false);
            } else {
              new Button(true, BtnType.PLAY_PASS);
            }
            // try {
            //   const arr = PokerHelper.hint(SetCardData.poker.pokers, SetCardData.poker.pokerSell.sellPokers);
            //   new SelectCard().autoselectPoker(arr);
            //   Log.success("出牌提示位置", SetCardData.poker, arr);
            // } catch (error) {
            //   this.ws.poker_paly_pass();//过
            // }
            Log.info('轮到我出牌', data);

            break;
          case 'CODE_SHOW_POKERS': //谁出的牌
            const pokersData: GAME_DATA = data;
            SetCardData.poker.lastSellId = pokersData.currentId;//暂存牌的数据
            SetCardData.clearPoker(pokersData.nextId);//清空上一次出的牌
            new SetCardData(pokersData).setHandsCard().setPlayCards(); //设置桌面数据
            new GamerState(pokersData.nextId).plass(true);//清空要不起
            new GamerState(pokersData.nextId).clock(pokersData.timeout);//显示倒计时
            new DesktopData(pokersData).setUser()
            Log.info(`出牌者ID:${pokersData.currentId}`, pokersData);
            break;
          case 'CODE_GAME_POKER_PLAY_PASS': //别人的过或者要不起
            const playpassData: POKER_PLAY_PASS = data;
            SetCardData.clearPoker(playpassData.clientId);//更具id清除玩家手上的牌
            new GamerState(playpassData.nextClientId).clock(playpassData.timeout);
            new GamerState(playpassData.clientId).plass();//更具id给玩家显示要不起
            if (playpassData.nextClientId == Game.uId) {
              // new GamerState().plass(playpassData.clientId, true);//如果自己要不起也
              if (!playpassData.trusted) {
                //如果玩家自己不是托管状态
                new Button(true, BtnType.PLAY_PASS);
                if (playpassData.nextClientId == playpassData.lastShellId) {
                  //如果其他两个玩家都要不起就隐藏自己要不起按钮
                  const btn = new Button(true, BtnType.PLAY_PASS);
                  btn.togglebtn(false, 0);//要不起按钮
                  btn.togglebtn(false, 1);//提示按钮
                }
              }
            }
            Log.info('过或者要不起', data);
            Tools.PlayAudio("过", Game.gamerInfoArr[playpassData.clientId].sex);
            break;
          case 'CODE_GAME_OVER': //游戏结束
            const GameOverData: GameOverType = data;
            this.unschedule(this.ws.heard_beat_);//结束心跳包
            Tools.GameExit(GameOverData);
            Log.info('游戏结束', data);
            break;
          case 'CODE_CLIENT_EXIT': //对局游戏退出
            Log.info('游戏退出', data);
            break;
          case 'CODE_GAME_ERROR':
            console.log('房间id已在游玩，当前玩家id和房间id原始玩家不匹配不能重连');
            break;
          case 'CODE_GAME_POKER_SPRING': //春天
            new AtlatsPlay(SkeletonType.chuntian);
            break;
          case 'CODE_ROOM_DESTROY'://
            new Util.Alert().ShowAlert({
              msg: '房主离开,即将返回大厅',
              cancel: false,
              confrm: true,
              callfun: function (type: BtnType_, node: Node): void {
                node.destroy();
                Loding.start_Loding("Main_");
              }
            })
            break;
        }
      }
    })
  }
  /**按钮事件 */
  btn_down(ev: Event) {
    const target: Node = ev.target as any;
    Log.info('按钮事件', target.name);
    switch (target.name) {
      case '开始游戏':
        this.ws.login({ id: String(Game.uId), version: '1.0.0', mode: '1' });//登录ws
        // Tools.PlayAudio("开始游戏");
        if (Game.TeamData.join) {//是否加入房间进来的
          this.ws.JOIN_ROOM(Game.TeamData.roomid);
          setGamer.OthersNode()//显示匹配中
        } else {
          if (Game.TeamData.create !== undefined) {//创建好友房
            this.ws.createCREATE_ROOM(Game.roomId)//好友房
          } else {//创建人机房
            this.ws.createPVE_ROOM(Game.roomId);//发起房间创建
          }
        }
        // this.ws
        break;
      case '抢地主':
        Tools.PlayAudio("抢地主");
        new GamerState(Game.uId).otherMsg(StateType.Elect_YES);
        this.ws.landlord_elect(true);
        break;
      case '不抢':
        Tools.PlayAudio("不抢");
        new GamerState(Game.uId).otherMsg(StateType.Elect_NO);
        this.ws.landlord_elect(false);
        break;
      case '不加倍':
        Tools.PlayAudio("不加倍");
        new GamerState(Game.uId).otherMsg(StateType.CHOOSE_0);
        this.ws.choose_double(1);
        break;
      case '加倍x2':
        Tools.PlayAudio("加倍");
        new GamerState(Game.uId).otherMsg(StateType.CHOOSE_2);
        // Folter.I.setFold(2)//更新自己节点的倍速
        this.ws.choose_double(2);
        // Folter.I.setFold(2)
        break;
      case '加倍x4':
        Tools.PlayAudio("加倍");
        new GamerState(Game.uId).otherMsg(StateType.CHOOSE_4);
        // Folter.I.setFold(4)//更新自己节点上的倍数显示
        this.ws.choose_double(4);
        // Folter.I.setFold(4)
        break;
      case '要不起':
        Tools.PlayAudio("要不起");
        this.ws.poker_paly_pass();
        PokerHelper.clear();
        break;
      case '出牌':
        const card_arr: string[] = Array.from(Game.I.selectCards).map((card_name) => card_name.match(/^\d+/g)[0]/*4-1截断成4*/);
        const card_arr_2 = card_arr.map(item => { return { level: Number(item), type: 1 } });
        let pokersell: PokerSell = null;
        if (!SetCardData.poker.pokerSell || SetCardData.poker.lastSellId !== Game.uId) {
          try {
            pokersell = new PokerSell(SetCardData.poker.pokerSell.sellType, SetCardData.poker.pokerSell.sellPokers, SetCardData.poker.pokerSell.coreLevel);
            // pokersell.setStraightCount(SetCardData.poker.pokerSell.straightCount);
          } catch (error) {
            console.log("自己是地主");
            this.ws.poker_play(card_arr);
            // return;
          }
        }
        let res = PokerHelper.checkSellValid(pokersell, card_arr_2);
        console.log("res=》》》》》", res);
        if (res > 0) {//出牌类型和对手不一样
          new Util.Alert().GameTips(`你应该出${res}张牌`)
        }
        if (res === -1) {//小于对家
          new Util.Alert().GameTips("出牌小于对家")
        }
        if (res === -2) {//牌型不对
          new Util.Alert().GameTips("出牌不符合")
        }
        if (res === 0) {
          this.ws.poker_play(card_arr);
          PokerHelper.clear();
        } else {
          return;
        }
        break;
      case '提示':
        try {
          Log.error("===========>poker", SetCardData.poker);
          const arr = PokerHelper.hint(SetCardData.poker.pokers, SetCardData.poker.pokerSell.sellPokers);
          new SelectCard().autoselectPoker(arr);
          if (arr.score === -1) {
            new Util.Alert().GameTips("要不起")
          }
          Log.success("出牌提示位置", SetCardData.poker, arr);
        } catch (error) {
          // console.log(error);
          // this.ws.poker_paly_pass();//过
        }
        return;
      //break
      case '托管':
        this.ws.change_trustee(true);
        break;
      case '取消托管':
        this.ws.change_trustee(false);
        break;
    }
    new Button(false);
  }
}

/**设置头像和name */
class setGamerInfo {
  constructor(node: Node, data: { avatar: string, clientNickname: string }) {
    const [iconNode, LabelNode] = node.children[0].children;//取出玩家节点的头像和name节点
    if (data.avatar !== '') {
      assetManager.loadRemote<ImageAsset>(data.avatar, { ext: ".jpg" }, (err, img_data) => {
        iconNode.getComponent(Sprite).spriteFrame = SpriteFrame.createWithImage(img_data);//设置头像
      });
    }
    LabelNode.children[0].getComponent(Label).string = data.clientNickname;//设置名字
  }
}

/**设置倍数 */
class DesktopData {
  private ScoreNode: Label;//低分倍数文字节点
  private florer: Folter;
  data: GAME_DATA;
  constructor(sucData: GAME_DATA) {
    this.data = sucData;
    this.ScoreNode = Game.I.scoreNode;
    this.florer = Game.I.florer;
  }
  setScore() {
    // this.ScoreNode.string = `低分${this.data.room.baseScore}   倍数${this.data.room.baseRate}`;
    this.ScoreNode.string = `房间号:${this.data.room.id}\t\t\t${new GameID().roomtitle}\t\t${Game.roomtitle}\t\t底分:${this.data.room.scoreInfo.baseScore}\t\t倍数:${this.data.room.scoreInfo.baseRate}`;
    return this;
  }
  setUser() {
    this.florer.Gold.string = new Util.Format(this.data.players[Game.uId].score).toString();//设置手持金币
    if (this.data.players[Game.uId].fan === 0) {//如果为0就是1倍
      this.florer.fold.string = '1';
    } else {
      this.florer.fold.string = this.data.players[Game.uId].fan.toString();
    }
    return this;
  }
}

/**去掉匹配中显示玩家卡片 */
export class setGamer {
  private Gmaer: Node[] = Game.I.Gamer_other;
  private join: JOIN_SUCCESS = null;
  constructor(joinData: JOIN_SUCCESS) {
    this.join = joinData;
  }
  /**初始化匹配状态 */
  static initState() {
    Game.I.Gamer_other.forEach(node => {
      node.children[0].active = false;
      node.children[1].active = true;
    });
  }
  /**切换显示----匹配中_玩家节点 */
  static toggleUI(Npc_Node: Node, show: boolean = true) {
    if (Npc_Node.children[0].name === '0') return;
    Npc_Node.children[0].active = show;
    Npc_Node.children[1].active = !show;
  }
  /**设置其他玩家的节点id---玩家加入时候设置节点 */
  others() {
    if (this.join.preId === Game.uId) {
      setGamer.toggleUI(this.Gmaer[0]);
      this.Gmaer[0].children[0].name = this.join.clientId.toString();
    } else {
      setGamer.toggleUI(this.Gmaer[1]);
      this.Gmaer[1].children[0].name = this.join.clientId.toString();
    }
    //Log.success('玩家节点数组', Game.I.Gamer);
  }
  /**显示隐藏其他玩家节点 */
  static OthersNode(show: boolean = true) {
    Game.I.Gamer_other.forEach(node => {
      node.active = show;
    })
  }
  /**设置自己的节点id */
  static selfID() {
    Log.success('玩家节点数组', Game.I.Gamer);
    const slefNode = Game.I.Gamer[0];//玩家自己的节点
    slefNode.name = Game.uId.toString();//设置玩家节点id
    const [iconNode, nameNode] = slefNode.children[0].children;
    new Gamer().setInfo(iconNode, nameNode.children[0]);//设置头像和name
    // Game.I.florer.setGold(new Gamer().coin);//设置玩家里的金币
  }
}

/**选牌功能 */
class SelectCard {
  selfHands: Node = Game.I.Hands[0];
  init_y: number = 0;
  constructor() {
    Game.I.selectCards.clear();//清空已选的牌数据
    this.offAlldown();//清空事件绑定
    this.init_y = this.selfHands.children[0].position.y;//储存一个默认的y位置
    this.selfHands.children.forEach((card) => card.on(Input.EventType.TOUCH_START, this.start, this));//绑定选点击事件
  }
  private start(ev: Event) {
    const node = ev.target as Node;
    const bol = Game.I.selectCards.has(node.name);
    if (bol) {
      Game.I.selectCards.delete(node.name);
    } else {
      Game.I.selectCards.add(node.name);
    }
    //变黑然后选中
    node.getComponent(Sprite).color = new Color(200, 200, 200, 255);
    setTimeout(() => {
      this.selectPoker(node, !bol);
      node.getComponent(Sprite).color = new Color(255, 255, 255, 255);
    }, 150);
  }
  private selectPoker(piker: Node, bol: boolean = true) {
    const { x, y, z } = piker.position;
    piker.setPosition(new Vec3(x, bol ? y + 10 : y - 10, z));
    if (bol) {
      Game.I.selectCards.add(piker.name);
    }
  }
  /**清空所有牌的点击事件 */
  offAlldown(ofent: boolean = true) {
    this.selfHands.children.forEach((card) => {
      const { x, z } = card.position;
      card.setPosition(x, this.init_y, z);//重置所有位置
      if (ofent) {
        card.off(Input.EventType.TOUCH_START);//去掉所有已经绑定的事件
      }
    });
  }
  /**提示选牌 */
  autoselectPoker(poker: Poker_1) {
    this.offAlldown(false);
    const pok_idx_arr = poker.positions;
    if (poker.positions.length > 0) {
      pok_idx_arr.forEach(idx => {
        this.selectPoker(this.selfHands.children[idx], true);
      });
    } else {
      // Game.I.ws.poker_paly_pass();
      // new Button(false);
      PokerHelper.clear();
    }
  }
}

enum StateType {
  /**不抢 */
  Elect_NO = "不抢",
  /**抢地主 */
  Elect_YES = "抢地主",
  /**不加倍 */
  CHOOSE_0 = "不加倍",
  /**加倍x2 */
  CHOOSE_2 = "加倍x2",
  /**加倍x4 */
  CHOOSE_4 = "加倍x4",
}
/**设置玩家状态消息 */
class GamerState {
  private Gamer: Node[] = Game.I.Gamer; //玩家节点下面的msg节点
  private Gamer_state = Game.I.gamerState; //状态预制体数组
  private gamers: { [key: string]: Node } = null;
  private id: number;
  constructor(id?: number) {
    this.id = id;
    this.gamers = {//初始化 玩家key:状态节点
      [this.Gamer[0].name]: this.Gamer[0].children[2],
      [this.Gamer[1].name]: this.Gamer[1].children[2],
      [this.Gamer[2].name]: this.Gamer[2].children[2],
    };
    // console.log("这是玩家们手里牌的数据", this.gamers);
  }
  /**提示要不起 */
  plass(destroy: boolean = false) {
    if (destroy) {
      this.gamers[this.id].getChildByName("state_pass")?.removeFromParent();
    } else {
      this.gamers[this.id].getChildByName("state_pass")?.removeFromParent();
      this.gamers[this.id].addChild(instantiate(this.Gamer_state[1]));

    }
  }
  /**玩家其他状态提示 */
  otherMsg(stateType: StateType) {
    const node = instantiate(this.Gamer_state[1]);
    switch (stateType) {
      case StateType.Elect_NO: node.getComponent(Label).string = "不抢"; break;
      case StateType.Elect_YES: node.getComponent(Label).string = "抢地主"; break;
      case StateType.CHOOSE_0: node.getComponent(Label).string = "不加倍"; break;
      case StateType.CHOOSE_2: node.getComponent(Label).string = "加倍x2"; break;
      case StateType.CHOOSE_4: node.getComponent(Label).string = "加倍x4"; break;
    }
    this.gamers[this.id].removeAllChildren();
    this.gamers[this.id].addChild(node);
    setTimeout(() => {
      this.gamers[this.id].removeChild(node);
    }, 500);
  }
  /**显示倒计时 */
  clock(time: number) {
    for (const key in this.gamers) this.gamers[key].removeAllChildren();//清空所有玩家状态节点下面的子节点
    Cliock.countTime = time;//设置倒计时长
    try {
      this.gamers[this.id].addChild(instantiate(this.Gamer_state[0]));
    } catch (error) {
      console.log(error);
    }
  }
}
/**给玩家添加地主牌 */
class SetLandlordCard {
  LandlordCard: Node = Game.I.LandlordCard;
  Hands: Node[] = Game.I.Hands;
  constructor(id: string, cardData: Poker[]) {
    const landlord_user_Node = this.Hands.filter((user) => user.name === id)[0];//找到地主手牌节点
    if (landlord_user_Node !== undefined) {
      landlord_user_Node.parent.getChildByName("地主图标").active = true;//显示地主图标
      this.LandlordCard.removeAllChildren(); //清空地主牌的头部子元素
      cardData.forEach((card) => {
        this.LandlordCard.addChild(Tools.getPick(card, 'landlord'));
        // if (Number(id) === Game.uId) {
        //   landlord_user_Node.addChild(Tools.getPick(card, 'self'));
        // } else {
        //   landlord_user_Node.addChild(Tools.getPick(card, 'others'));
        //   landlord_user_Node.parent.children[5].children[0].getComponent(Label).string = landlord_user_Node.children.length.toString();//设置手里牌count数
        // }
      });
    }
  }
}

/**设置桌面数据添加牌 */
class SetCardData {
  private Hands: Node[] = Game.I.Hands;
  private Gamer: Node[] = Game.I.Gamer;
  private PlayCards: Node[] = Game.I.PlayCards;
  private Data: GAME_DATA = null;
  //**用来存临时的牌 */
  static poker: { pokerSell: Poker_1, pokers: Poker[], lastSellId: number } = {
    pokerSell: undefined,
    pokers: [],
    lastSellId: 0
  };
  constructor(data: GAME_DATA) {
    this.Hands.forEach((node) => node.removeAllChildren()); //清空子节点的牌
    Object.keys(data.players).forEach(key => {//倒叙一下手里牌
      data.players[key].pokers.reverse()
    })
    this.Data = data;
    //console.log("设置提示牌数据");
    SetCardData.poker.pokers = JSON.parse(JSON.stringify(this.Data.players[String(Game.uId)].pokers));
    SetCardData.poker.pokerSell = this.Data.pokerSell !== undefined ? JSON.parse(JSON.stringify(this.Data.pokerSell)) : undefined;
    //牌型数据
    if (this.Data.pokerSell !== undefined) {
      const data = this.Data.pokerSell;
      // console.log("牌型数据=>>>>>>>>>>>>", this.Data.pokerSell);
      console.log("出牌数据==============>", this.Data);
      try {
        Tools.PlayAudio(`${data.coreLevel}_${data.sellType}`, this.Data.players[this.Data.currentId].sex);//播放单个双个音效
        Tools.PlayAudio2(data.sellType, this.Data.players[this.Data.currentId].sex);//播放特别牌型音效
        AtlatsPlay.topaly(data.sellType);//播放特别牌型动画
      } catch (error) {
        console.error('数据错误数音频播放失败!');
      }
    }
  }
  /**设置指定玩家托管状态 */
  static setTrusted(gamerID: number, trusted: boolean = true) {
    const gamers = Game.I.Gamer;
    const trust_node = {
      [gamers[0].name]: Game.I.Escrow,//玩家托管节点
      [gamers[1].name]: gamers[1].children[3],//下家托管节点
      [gamers[2].name]: gamers[2].children[3],//上家托管节点
    }
    trust_node[gamerID].active = trusted;//设置玩家托管节点状态
  }
  /**初始化所有玩家托管状态 */
  private setEscrow() {
    const key: string = this.Gamer[0].name;
    const trusted: boolean = this.Data.players[key].trusted;
    Game.I.Escrow.active = trusted;
    if (trusted) {//如果为托管状态就隐藏所有自己的按钮
      new Button(false);
    }
    //设置其他两个玩家的状态
    for (let i = 1; i < 3; i++) {
      const key = this.Gamer[i].name;
      //Log.error("id为", key, "的玩家状态", this.Data.players[key])
      const trusted = this.Data.players[key].trusted;
      this.Gamer[i].children[3].active = trusted;
    }
  }
  /**设置玩家已经出的牌 */
  setPlayCards() {
    //SetCardData.clearPoker(this.Data.preId);
    this.PlayCards.forEach(PlayCards_node => {
      if (Number(PlayCards_node.name) === this.Data.currentId) {
        PlayCards_node.removeAllChildren();
        if (this.Data.pokerSell !== undefined) {
          this.Data.pokerSell.sellPokers.forEach(pikers => {
            PlayCards_node.addChild(Tools.getPick(pikers, "centent"));
          });
        }
      }
    });
    return this;
  }
  /**设置玩家手里牌 */
  setHandsCard() {
    this.setEscrow();
    let type: 'self' | 'others' | 'landlord' | 'centent' = "self";
    this.Hands.forEach(gamer_node => {
      this.Data.players[gamer_node.name].pokers.forEach(poker => {
        if (gamer_node.name === String(Game.uId)) {
          gamer_node.addChild(Tools.getPick(poker, "self"));//设置自己手里牌
        } else {
          gamer_node.addChild(Tools.getPick(poker, "others"));//设置其他玩家手里牌
          // const count = String(this.Data.players[gamer_node.name].pokers.length);//其他玩家手里一共有多少张牌
          //查找到其他玩家显示牌张数的节点
          gamer_node.parent.children[5].children[0].getComponent(Label).string = gamer_node.children.length.toString();
        }
      });
    });
    try {
      new SelectCard();
    } catch (error) {
      console.error('手里没牌不能设置选牌');
    }
    return this;
  }
  /**更具玩家id设置好上下家位置 */
  setGamerID() {
    const players = this.Data.players;
    const id_s = Object.keys(players);//把players对象依据key变string数组
    const self_idx = id_s.filter(key => key == String(Game.uId))[0];//依据filter过滤取到玩家的key
    const self_data = players[self_idx];//更具key在players里面拿到本玩家的key
    const gamer_list = [self_data.id, self_data.next, self_data.pre].map(item => String(item));//更具node节点重新排序上下家id
    gamer_list.forEach((id, idx) => {
      this.Gamer[idx].name = id;//设置手牌节点id
      this.Hands[idx].name = id;//设置玩家节点id
      this.PlayCards[idx].name = id;//玩家已出牌位置node的id
    });
    // this.Gamer.forEach(gamer => {
    //   gamer.children[0].children[1].children[0].getComponent(Label).string = gamer.name;//设置玩家name
    // })
    // console.log("玩家节点", this.Gamer);
    return this;
  }
  /**清空上已出的牌 */
  static clearPoker(preid: number) {
    Game.I.PlayCards.forEach(PlayCards_node => {//已经出的牌
      if (PlayCards_node.name === String(preid)) {
        PlayCards_node.removeAllChildren();
      }
    });
  }
}
export enum BtnType {
  /**开始游戏 */
  GAME_STARTING = 0,
  /**抢地主 */
  LANDLORD_ELECT,
  /**加倍 */
  JIA_BEI,
  /**出牌 */
  PLAY_PASS,
}

/**按钮显示 */
export class Button {
  ws: Socket = Game.I.ws;
  btns: Node = Game.I.ButtonGroup;//出牌操作按钮数组
  otherbtns: Node[] = Game.I.OthersBtns;//其他按钮数组
  idx: number = 0;//用户id
  constructor(show: boolean, btn_idx?: BtnType) {
    if (show) {
      this.idx = btn_idx;
      this.btns.children.forEach((btn) => (btn.active = false)); //隐藏所有按钮
      this.btns.children[btn_idx].active = true;//显示指定的按钮组
      if (btn_idx == BtnType.PLAY_PASS) {//如果是出牌按钮就设置选牌功能
        // new SelectCard();
        this.togglebtn(true, 0);//显示要不起按钮
        this.togglebtn(true, 1);//显示提示按钮
      }
    } else {
      this.btns.children.forEach((btn) => (btn.active = false)); //隐藏所有按钮
    }
  }
  /**详细设置第几个按钮显示隐藏 */
  togglebtn(show: boolean = true, idx: number = 0) {
    this.btns.children[this.idx].children[idx].active = show;
  }
}

/**后端给的牌型枚举 */
enum SellType {
  ILLEGAL,    //非合法
  SINGLE,     //单个牌
  DOUBLE,     //对子牌
  THREE,      //三张牌
  THREE_ZONES_SINGLE,//三带单
  THREE_ZONES_DOUBLE,//三带对
  FOUR_ZONES_SINGLE,  //四带单
  FOUR_ZONES_DOUBLE,   //四带对
  SINGLE_STRAIGHT,    //单顺子
  DOUBLE_STRAIGHT, //双顺子
  THREE_STRAIGHT,  //三顺子
  FOUR_STRAIGHT,    //四顺子
  THREE_STRAIGHT_WITH_SINGLE, //飞机带单牌
  THREE_STRAIGHT_WITH_DOUBLE,   //飞机带对牌
  FOUR_STRAIGHT_WITH_SINGLE,   //四顺子带单
  FOUR_STRAIGHT_WITH_DOUBLE,   //四顺子带对
  BOMB,       //炸弹
  KING_BOMB,  //王炸
}
/**前端的牌型动画类型 */
enum SkeletonType {
  /**春天 */
  chuntian,
  /**炸弹 */
  zhadan,
  /**王炸 */
  wangzha,
  /**顺子 */
  shunzi,
  /**连对 */
  liandui,
  /**飞机 */
  feiji
}
//**牌型动画 */
class AtlatsPlay {
  atlats_node: Node = Game.I.atlats;
  skeletonS: sp.SkeletonData[] = Game.I.skeletonS;
  constructor(idx: SkeletonType) {
    try {
      let skelet: sp.Skeleton = null;
      const skeletData: sp.SkeletonData = this.skeletonS[idx];
      if (idx === SkeletonType.feiji) {//如果类型是飞机这种位移动画
        skelet = this.atlats_node.children[1].getComponent(sp.Skeleton);
      } else {
        skelet = this.atlats_node.children[0].getComponent(sp.Skeleton);
      }
      skelet.skeletonData = skeletData;
      skelet.clearTracks();
      skelet.addAnimation(0, 'animation', false);
      console.log("播放动画代码执行结束");
    } catch (error) {
      Log.error("牌型没有动画!!!");
    }
  }
  static topaly(idx: SellType) {
    switch (idx) {
      case SellType.BOMB: new AtlatsPlay(SkeletonType.zhadan); break;//炸弹
      case SellType.KING_BOMB: new AtlatsPlay(SkeletonType.wangzha); break;//王炸
      case SellType.SINGLE_STRAIGHT: new AtlatsPlay(SkeletonType.shunzi); break;//顺子
      case SellType.DOUBLE_STRAIGHT: new AtlatsPlay(SkeletonType.liandui); break;//连对
      case SellType.THREE_STRAIGHT_WITH_SINGLE: new AtlatsPlay(SkeletonType.feiji); break;//飞机
      case SellType.THREE_STRAIGHT_WITH_DOUBLE: new AtlatsPlay(SkeletonType.feiji); break;//飞机
    }
  }
}

class GamerStart {
  constructor() {
    // Game.I.clearing.active = true;//隐藏结束面板
    console.log('yzt', Game.I);
    Game.I.Gamer_other.forEach(gamer => {//显示其他玩家牌的张数
      const other = gamer.children[0];
      other.children[1].getComponent(Layout).spacingX = -52;
      other.children[5].active = true
    })
    Game.I.Gamer.forEach(gamer => {
      gamer.getChildByName('地主图标').active = false;//清空地主状态
      gamer.children[1].removeAllChildren();//清空手里牌
    })
    Game.I.PlayCards.forEach(gamer => gamer.removeAllChildren())//清空已经打出的牌
    Game.I.clearing.active = false;//隐藏结算面板
  }
}
/**游戏结束 */
class GameOver {
  private otherGamer: Node[];
  constructor() {
    this.otherGamer = Game.I.Gamer.filter(gamer => gamer.name != String(Game.uId));//找到其他两个玩家的节点
  }
  showPoker() {
    this.otherGamer.forEach(gamer => {
      gamer.children[1].getComponent(Layout).spacingX = -26;
      gamer.children[5].active = false;
    })
  }
}

//**对于Game的工具类 */
class Tools {
  /**根据car_name找到预制体资源并且实例化成node节点返回
   * @param card_name 扑克牌的对象
   * @param type 预制体资源 self玩家 others其他玩家 landlord地主牌 centent玩家们已经出的牌
   * @param type2 slef玩家 others其他玩家
   */
  static getPick(card: Poker, type: 'self' | 'others' | 'landlord' | 'centent', type2?: 'self' | 'others'): Node {
    /**拼接牌的名字格式为 牌值_牌的类型 */
    const card_name = `${card.level}_${card.type}`;//拼接牌的name
    const frame: SpriteFrame = Game.I.playingCard.filter((sp_frame) => sp_frame.name === card_name)[0];//找到牌的资源
    let card_Node: Node = null;//初始化一个Node的节点
    if (frame !== undefined) {
      const item = ['self', 'others', 'landlord', 'centent'].indexOf(type);
      card_Node = instantiate(Game.I.PickPrefabs[item]);//实例化出对应type牌的节点
      card_Node.getComponent(Sprite).spriteFrame = frame;//设置spriteframe图片资源
      card_Node.name = card_name;//给当前实例化好的node牌节点设置对应的name
      // if (type2 === 'others') {//others = 其他它玩两家的牌  就设置做对应的设置
      //   card_Node.getComponent(UITransform).width = 50;
      //   card_Node.getComponent(UITransform).height = 100;
      // }
    } else Log.error('找不到对于card数据的牌！', card);
    return card_Node;
  }
  /**播放音效 */
  static PlayAudio(fileNmae: string, sex: 0 | 1 | number = 0) {
    const audioNode = Game.I.audioNode;
    let sexName = sex === 0 ? 'boy' : 'garl';
    resources.load(`audio/game/${sexName}/${fileNmae}`, AudioClip, (err, suc) => {
      if (!err) {
        audioNode.clip = suc;
        if (audioNode.enabled) {//如果节点为激活状态就播放
          audioNode.play();
        }
        // console.log("加载的音频资源", suc);
      } else {
        Log.error(`没找到名为:${fileNmae}的音频资源`);
      }
    })
  }
  static PlayAudio2(type: number, sex: 0 | 1 | number = 0) {
    switch (type) {
      case SellType.BOMB: this.PlayAudio("炸弹", sex); break;
      case SellType.KING_BOMB: this.PlayAudio("王炸", sex); break;
      case SellType.THREE: this.PlayAudio("个3", sex); break;
      case SellType.DOUBLE_STRAIGHT: this.PlayAudio("连对", sex); break;
      case SellType.THREE_ZONES_SINGLE: this.PlayAudio("带3_1", sex); break;
      case SellType.THREE_ZONES_DOUBLE: this.PlayAudio("带3_2", sex); break;
      case SellType.SINGLE_STRAIGHT: this.PlayAudio("顺子", sex); break;
      case SellType.THREE_STRAIGHT_WITH_SINGLE: this.PlayAudio("飞机", sex); break;
    }
  }
  //对局打完
  static GameExit(data: GameOverType) {
    Game.I.Escrow.active = false; //隐藏托管面板
    Game.I.Gamer.forEach(gamer => gamer.children[2].removeAllChildren());//清空所有玩家状态
    Game.fold = 1;//低分设置为空
    Game.scroe = 0;//
    Header.GAME_OVER = true;
    Clearing.overData = data;//传结算数据给计分面板
    new GameOver().showPoker();//显示玩家手里牌
    setTimeout(() => {
      Game.I.clearing.active = true;
    }, 500);
  }
}